package com.tcoiss.common.component.service.impl;

import com.tcoiss.common.component.dataentity.TypesContainer;
import com.tcoiss.common.component.service.DispatchService;
import com.tcoiss.common.core.exception.CustomException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DispatchServiceImpl implements DispatchService {

    private Map<String, Object> serviceObjectMap = new ConcurrentHashMap();
    private Map<String, Method> serviceMethodMap = new ConcurrentHashMap();


    public Object invoke(String appServiceFacory, String serviceName, String methodName, Object... paras) {
        Class factory = TypesContainer.getOrRegister(appServiceFacory);
        String serviceKey = appServiceFacory + serviceName;

        Object arg13;
        String msg;
        try {


                try {
                    Object serviceObject = this.serviceObjectMap.get(serviceKey);
                    if (serviceObject == null) {
                        Map serviceMethod = this.serviceObjectMap;
                        synchronized (this.serviceObjectMap) {
                            serviceObject = this.serviceObjectMap.get(serviceKey);
                            if (serviceObject == null) {
                                serviceObject = factory.getMethod("getService", new Class[]{String.class})
                                        .invoke((Object) null, new Object[]{serviceName});
                                this.serviceObjectMap.put(serviceKey, serviceObject);
                            }
                        }
                    }
                    Method serviceMethod1 = this.findServiceMethod(serviceObject.getClass(), methodName,
                            paras == null ? 0 : paras.length);

                    arg13 = serviceMethod1.invoke(serviceObject, paras);
                } catch (Throwable arg49) {
                    throw arg49;
                }

            return arg13;
        } catch (NoSuchMethodException arg53) {
            this.setResponseError(arg53);
            msg = String.format("调用服务%s.%s的方法%s失败:%s",
                    new Object[]{"tcoiss", serviceName, methodName, arg53.getMessage()});
            throw new RuntimeException(msg, arg53);
        } catch (SecurityException arg54) {
            this.setResponseError(arg54);
            msg = String.format("调用服务%s.%s的方法%s失败:%s",
                    new Object[]{"tcoiss", serviceName, methodName, arg54.getMessage()});
            throw new RuntimeException(msg, arg54);
        } catch (IllegalAccessException arg55) {
            this.setResponseError(arg55);
            msg = String.format("调用服务%s.%s的方法%s失败:%s",
                    new Object[]{"tcoiss", serviceName, methodName, arg55.getMessage()});
            throw new RuntimeException(msg, arg55);
        } catch (IllegalArgumentException arg56) {
            this.setResponseError(arg56);
            msg = String.format("调用服务%s.%s的方法%s失败:%s",
                    new Object[]{"tcoiss", serviceName, methodName, arg56.getMessage()});
            throw new RuntimeException(msg, arg56);
        } catch (InvocationTargetException arg57) {
            msg = String.format("调用服务%s.%s的方法%s失败:%s",new Object[]{"tcoiss", serviceName, methodName,
                            arg57.getTargetException().getMessage()});
            this.setResponseError(arg57);
            if (arg57.getTargetException() instanceof RuntimeException) {
                throw (RuntimeException) arg57.getTargetException();
            } else {
                throw new RuntimeException(msg, arg57.getTargetException());
            }
        }
    }

    private void setResponseError(Exception e) {
        if (e instanceof InvocationTargetException) {
            for (Throwable sube = ((InvocationTargetException) e).getTargetException(); sube != null; sube = sube
                    .getCause()) {
                if (sube instanceof CustomException) {
                    return;
                }
            }
        }
    }

    private Method findServiceMethod(Class<?> clazz, String method, int paramterLength) {
        String key = clazz.getName() + '#' + method + '#' + paramterLength;
        Method serviceMethod = this.serviceMethodMap.get(key);
        if (serviceMethod == null) {
            Map serviceMethodMap = this.serviceMethodMap;
            synchronized (this.serviceMethodMap) {
                serviceMethod = this.serviceMethodMap.get(key);
                if (serviceMethod == null) {
                    Method[] arg6 = clazz.getMethods();
                    int arg7 = arg6.length;

                    for (int arg8 = 0; arg8 < arg7; ++arg8) {
                        Method m = arg6[arg8];
                        if (m.getName().equalsIgnoreCase(method) && m.getParameterCount() == paramterLength) {
                            serviceMethod = m;
                            this.serviceMethodMap.put(key, m);
                            break;
                        }
                    }
                }
            }

            if (serviceMethod == null) {
                throw new CustomException(9999,new Object[]{clazz.getName(), method},"未发现类%s的方法%s");
            }
        }

        return serviceMethod;
    }


}
